package com.parking.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.parking.common.core.model.RedisKey;
import com.parking.common.core.model.StateData;
import com.parking.common.web.util.RedisUtil;
import com.parking.common.web.util.SmsUtil;
import com.parking.dto.UserInfoDto;
import com.parking.dto.UserPhoneForm;
import com.parking.exception.UserException;
import com.parking.exception.UserExceptionCode;
import com.parking.form.AddUserForm;
import com.parking.form.UserLoginForm;
import com.parking.user.dao.UserCarMapper;
import com.parking.user.dao.UserInfoMapper;
import com.parking.user.dao.UserLoginLogsMapper;
import com.parking.user.entity.UserAccount;
import com.parking.user.dao.UserAccountMapper;
import com.parking.user.entity.UserCar;
import com.parking.user.entity.UserInfo;
import com.parking.user.entity.UserLoginLogs;
import com.parking.user.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 香菜狗带
 * @since 2023年11月28日
 */
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {
     @Autowired
     private UserAccountMapper userAccountMapper;
     @Autowired
     private UserLoginLogsMapper userLoginLogsMapper;
    @Autowired
     private UserInfoMapper userInfoMapper;
    @Autowired
     private RedisUtil redisUtil;
    @Autowired
    private SmsUtil smsUtil;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Resource
    private UserCarMapper userCarMapper;


    /***
     * 登录方法
     * 参数：
     ("用户账号")：userAccount;
     ("用户密码")：userPass;
     ("请求头"):response
     */
    @Override
    public UserInfoDto userLogin(UserLoginForm form, HttpServletResponse response) {
        //登录判断
        System.out.println("/////////////////////////");
        System.out.println("测试"+form);
        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_account",form.getUserAccount());
        wrapper.eq("user_pass",form.getUserPass());
        UserAccount user = userAccountMapper.selectOne(wrapper);
        if(user==null){
            throw new UserException(UserExceptionCode.LOGIN_FAILED);
        }
        if(user.getUserState()!=StateData.USER_LOGS_ISNOT_LOGIN){
            throw new UserException(UserExceptionCode.USER_STATE_IDNOT);
        }
        //判断是否登录
//        QueryWrapper<UserLoginLogs> loginWrapper = new QueryWrapper<>();
//        loginWrapper.eq("user_account_id",user.getUserId());
//        UserLoginLogs logs = userLoginLogsMapper.selectOne(loginWrapper);
//        if (ObjectUtil.isNotEmpty(logs)) {
//            if (logs.getUserLoginState()==StateData.USER_LOGS_ISNOT_LOGIN) {
//                throw new UserException(UserExceptionCode.USER_LOGGED_IN);
//            }
//        }
        QueryWrapper<UserInfo> userWrapper = new QueryWrapper<>();
        userWrapper.eq("user_account_id",user.getUserId());
        UserInfo userInfo = userInfoMapper.selectOne(userWrapper);
        UserInfoDto dto = BeanUtil.toBean(userInfo, UserInfoDto.class);
        dto.setUserAccount(user.getUserAccount());
        QueryWrapper<UserCar> carWrapper = new QueryWrapper<>();
        carWrapper.eq("user_info_id",userInfo.getUserInfoId());
        List<UserCar> userCars = userCarMapper.selectList(carWrapper);
        dto.setUserCars(userCars);
        //用户登录日志储存在消息队列
        UserLoginLogs userLoginLogs = new UserLoginLogs();
        userLoginLogs.setUserLoginAccount(user.getUserAccount());
        userLoginLogs.setUserAccountId(user.getUserId());
        userLoginLogs.setUserLoginTime(LocalDateTime.now());
        userLoginLogs.setUserLoginState(StateData.USER_LOGS_ISNOT_LOGIN);
        HashMap<String, Object> map = new HashMap<>();
        map.put("userLoginLogs",userLoginLogs);
        rabbitTemplate.convertAndSend("userLoginLogs",map);
        return dto;
    }
    /***
     * 退出登录方法
     * 参数：
     ("用户Id")：userId;
     */
    @Override
    public void LogOff(String userAccount) {
        QueryWrapper<UserLoginLogs> wrapper = new QueryWrapper<>();
        wrapper.eq("user_login_account",userAccount);
        wrapper.eq("user_login_state",StateData.USER_LOGS_ISNOT_LOGIN);
        wrapper.orderByDesc("user_log_time");
        wrapper.last("LIMIT 1");
        UserLoginLogs logs = userLoginLogsMapper.selectOne(wrapper);
        if (logs==null) {
            throw new UserException(UserExceptionCode.USER_INFO_NO_LOGIN);
        }
        System.out.println(logs+"===========================");
            logs.setUserLoginState(StateData.USER_LOGS_LOGIN);
            userLoginLogsMapper.updateById(logs);

    }

    /***
     * 用户注册
     * 参数：
     ("用户账号")：userAccount;
     ("用户密码")：userPass;
     ("用户名称")：userInfoName;
     ("用户电话")：userInfoTel;
     ("用户身份证号")：userInfoCard;
     */
    @Transactional
    @Override
    public void addUserAccount(AddUserForm form) {
        System.out.println(redisUtil.get(RedisKey.userRegisterCodeOnMinute(form.getUserInfoTel())));
        String code = redisUtil.get(RedisKey.userRegisterCode(form.getUserInfoTel()));
        System.out.println("验证码"+code);
        if (code==null||!form.getCode().equals(code)) {
            throw new UserException(UserExceptionCode.USERINFO_PHONE_CODE);
        }
        QueryWrapper<UserInfo> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("user_info_tel",form.getUserInfoTel());
        UserInfo userInfo = userInfoMapper.selectOne(wrapper1);
        if (userInfo!=null) {
            throw new UserException(UserExceptionCode.USER_INFO_TEL);
        }
        QueryWrapper<UserAccount> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("user_account",form.getUserAccount());
        UserAccount account = userAccountMapper.selectOne(wrapper2);
        if (account!=null) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_INNOT);
        }
        //用户账号信息
        UserAccount userAccount = BeanUtil.toBean(form, UserAccount.class);
        userAccount.setUserState(StateData.USER_STATE_ENABLE);
        userAccount.setUserAddTime(LocalDateTime.now());
        userAccountMapper.insert(userAccount);
        //用户信息
        UserInfo user = BeanUtil.toBean(form, UserInfo.class);
        user.setUserAccountId(userAccount.getUserId());
        user.setUserRealNameState(StateData.USER_REALNAME_STATE_ISNOT);
        user.setUserInfoImg("https://algebraic-toposes.oss-cn-chengdu.aliyuncs.com/df5304e47a2c49ec9afecd69cce312ee.jpg");
        userInfoMapper.insert(user);
        //消息队列修改日志信息
        userAccount.setUserAddTime(LocalDateTime.now());
        HashMap<String, Object> map = new HashMap<>();
        map.put("userAccount",userAccount);
        rabbitTemplate.convertAndSend("addUserAccount",map);



    }
    /***
     * 用户注册验证码
     * 参数：
     * ("用户电话")：userInfoTel;
     */
    @Override
    public void sendRegisterCode(String phone) throws Exception {

        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_info_tel",phone);
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);

        if (userInfo!=null) {
            throw new UserException(UserExceptionCode.USER_INFO_TEL);
        }
        //一分钟内不能再次发送手机验证码
        if (redisUtil.exist((RedisKey.userRegisterCodeOnMinute(phone)))) {
            throw new UserException(UserExceptionCode.USERINFO_PHONE_ONE_MINUTER);
        }
        //消息队列修改日志信息
        HashMap<String, Object> map = new HashMap<>();
        map.put("phone",phone);
        rabbitTemplate.convertAndSend("sendRegisterCode",map);

    }
    /***
     * 用户验证码登录
     * 参数：
     ("验证码")：code;
     ("用户手机号")：userInfoTel;
     */
    @Override
    public UserInfoDto codeLogin(UserPhoneForm form) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_info_tel",form.getPhone());
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        if (userInfo==null) {
          throw new UserException(UserExceptionCode.USERINFO_IS_NOT);
        }
        UserAccount account = userAccountMapper.selectById(userInfo.getUserAccountId());
        if (account.getUserState()!= StateData.USER_STATE_ENABLE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_ISNOT);
        }
        System.out.println("测试"+redisUtil.get(RedisKey.userLoginCodeOnMinute(form.getPhone())));
        System.out.println("测试"+redisUtil.get(RedisKey.userLoginCode(form.getPhone())));
        //判断验证码
        String code = redisUtil.get(RedisKey.userLoginCode(form.getPhone()));
        if (!form.getCode().equals(code)) {
            throw new UserException(UserExceptionCode.USERINFO_PHONE_CODE_ISNO);
        }
        //判断是否登录
        QueryWrapper<UserLoginLogs> loginWrapper = new QueryWrapper<>();
        loginWrapper.eq("user_account_id",account.getUserId());
        UserLoginLogs logs = userLoginLogsMapper.selectOne(loginWrapper);
        if (ObjectUtil.isNotEmpty(logs)) {
            if (logs.getUserLoginState()==StateData.USER_LOGS_ISNOT_LOGIN) {
                throw new UserException(UserExceptionCode.USER_LOGGED_IN);
            }
        }
        UserInfoDto dto = BeanUtil.toBean(userInfo, UserInfoDto.class);
        dto.setUserAccount(account.getUserAccount());
        //消息队列修改日志信息
        HashMap<String, Object> map = new HashMap<>();
        map.put("userAccountId",account.getUserId());
        map.put("userAccount",account.getUserAccount());
        map.put("userLoginTime",LocalDateTime.now());
        map.put("phone",form.getPhone());
        rabbitTemplate.convertAndSend("codeLogin",map);
        return dto;
    }
    /**
     * 启用用户状态
     * 参数
     * 令牌：authorization
     * 账号状态：state
     * */
    @Transactional
    @Override
    public void enableStateById( Integer userId, Integer platformId) {
        UserAccount account = userAccountMapper.selectById(userId);
        if (account==null) {
            throw new UserException(UserExceptionCode.USERINFO_IS_NOT);
        }
        if (account.getUserState()==StateData.USER_STATE_DELETE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_DELECT);
        }
        if (account.getUserState()==StateData.USER_STATE_ENABLE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_ENABLE);
        }
        account.setUserState(StateData.USER_STATE_ENABLE);
        userAccountMapper.updateById(account);
        //消息队列修改日志信息
        account.setUserUpdatePerson(String.valueOf(platformId));
        account.setUserUpdateTime(LocalDateTime.now());
        HashMap<String, Object> map = new HashMap<>();
        map.put("userAccount",account);
        rabbitTemplate.convertAndSend("upStateById",map);
    }
    /**
     * 禁用用户状态
     * 参数
     * 令牌：authorization
     * 账号状态：state
     * */
    @Override
    @Transactional
    public void downStateById(Integer userId, Integer platformId) {
        UserAccount account = userAccountMapper.selectById(userId);
        if (account==null) {
            throw new UserException(UserExceptionCode.USERINFO_IS_NOT);
        }
        if (account.getUserState()==StateData.USER_STATE_DELETE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_DELECT);
        }
        if (account.getUserState()==StateData.USER_STATE_DISABLE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_DOWN);
        }
        account.setUserState(StateData.USER_STATE_DISABLE);
        userAccountMapper.updateById(account);
        //消息队列修改日志信息
        account.setUserUpdatePerson(String.valueOf(platformId));
        account.setUserUpdateTime(LocalDateTime.now());
        HashMap<String, Object> map = new HashMap<>();
        map.put("userAccount",account);
        rabbitTemplate.convertAndSend("upStateById",map);
    }
    /**
     * 删除用户
     * 参数
     * 令牌：authorization
     * 账号状态：state
     * */
    @Override
    @Transactional
    public void deleteStateById(Integer userId, Integer platformId) {
        UserAccount account = userAccountMapper.selectById(userId);
        if (account==null) {
            throw new UserException(UserExceptionCode.USERINFO_IS_NOT);
        }
        if (account.getUserState()==StateData.USER_STATE_DELETE) {
            throw new UserException(UserExceptionCode.USER_ACCOUNT_STATE_DELECT);
        }
        account.setUserState(StateData.USER_STATE_DELETE);
        userAccountMapper.updateById(account);
        //消息队列修改日志信息
        account.setUserUpdatePerson(String.valueOf(platformId));
        account.setUserUpdateTime(LocalDateTime.now());
        HashMap<String, Object> map = new HashMap<>();
        map.put("userAccount",account);
        rabbitTemplate.convertAndSend("upStateById",map);
    }
    /***
     * 用户登录验证码
     * 参数：
     * ("用户电话")：userInfoTel;
     */
    @Override
    public void sendLoginCode(String phone) {
        System.out.println("参数"+phone);
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_info_tel",phone);
        UserInfo user=userInfoMapper.selectOne(wrapper);
        System.out.println(user);
        if (user==null) {
            throw new UserException(UserExceptionCode.USERINFO_IS_NOT);
        }
        UserAccount userAccount = userAccountMapper.selectById(user.getUserAccountId());
        System.out.println("参数"+userAccount.toString());
        if (userAccount.getUserState()!= StateData.USER_STATE_ENABLE) {
            throw new UserException(UserExceptionCode.USER_STATE_IDNOT);
        }
        if (redisUtil.exist(RedisKey.userLoginCodeOnMinute(phone))) {
            throw new UserException(UserExceptionCode.USERINFO_PHONE_ONE_MINUTER);
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("phone",phone);
        rabbitTemplate.convertAndSend("sendLoginCode",map);
    }


}
